package cn.base.web.gateway.exception;

import cn.rengy.auth.exception.AuthException;
import cn.rengy.lang.ResultEntity;
import cn.rengy.tool.core.util._NumberUtils;
import cn.rengy.util.ExceptionPrintUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ResponseStatusException;
import reactor.core.publisher.Mono;

import java.util.stream.Collectors;

@Slf4j
@Component
public class CustomErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {


    public CustomErrorWebExceptionHandler(ErrorAttributes errorAttributes,
                                          WebProperties webProperties,
                                          ObjectProvider<ViewResolver> viewResolvers,
                                          ServerProperties serverProperties,
                                          ServerCodecConfigurer serverCodecConfigurer,
                                          ApplicationContext applicationContext) {
        super( errorAttributes,  webProperties.getResources(),  serverProperties.getError(),  applicationContext);
        this.setViewResolvers(viewResolvers.orderedStream().collect(Collectors.toList()));
        this.setMessageWriters(serverCodecConfigurer.getWriters());
        this.setMessageReaders(serverCodecConfigurer.getReaders());
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    @Override
    protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
        Throwable throwable = getError(request);
        if (throwable instanceof GatewayAuthException) {
            return ServerResponse.status(((GatewayAuthException) throwable).getHttpStatus())
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(BodyInserters.fromValue(ResultEntity.fail(throwable.getMessage())));
            ////MediaType.APPLICATION_JSON_UTF8弃用，根据 RFC 8259，JSON 的默认编码已是 UTF-8，因此显式声明 _utf8 是冗余的
        }else {
            log.error(ExceptionPrintUtils.getTrace(throwable));
            return ServerResponse.status(500)
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(BodyInserters.fromValue(ResultEntity.fail(throwable.getMessage())));
        }
    }
}
